home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume13 / rolodex / part02 < prev    next >
Encoding:
Internet Message Format  |  1988-01-30  |  57.1 KB

  1. Subject:  v13i050:  Screen-oriented rolodex program, Part02/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dave Ihnat <ihnp4!homebru!ignatz>
  7. Posting-number: Volume 13, Issue 50
  8. Archive-name: rolodex/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 2 (of 4)."
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f './datadef.h' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'./datadef.h'\"
  20. else
  21. echo shar: Extracting \"'./datadef.h'\" \(2603 characters\)
  22. sed "s/^X//" >'./datadef.h' <<'END_OF_FILE'
  23. X/* datadef.h */
  24. X#define ABORTSTRING "\\"
  25. X#define ABORTCHAR '\\'
  26. X
  27. X#define MAXMATCHES 17
  28. X
  29. X#define N_BASIC_FIELDS 8
  30. X#define OTHER -1
  31. X
  32. X#ifdef UNIX
  33. X#ifdef SYS5
  34. X#define rindex(a,b) strrchr(a,b)
  35. X#define index(a,b) strchr(a,b)
  36. X#endif
  37. X#ifdef BSD
  38. X#include <string.h>
  39. X#endif
  40. X#endif
  41. X
  42. Xtypedef enum Basic_Field {
  43. X
  44. X    R_NAME = 0, R_WORK_PHONE, R_HOME_PHONE, R_COMPANY, R_WORK_ADDRESS,
  45. X    R_HOME_ADDRESS, R_REMARKS, R_UPDATED
  46. X
  47. X  };    
  48. X    
  49. Xextern char *Field_Names[];  
  50. X  
  51. X/* A Rolodex entry */
  52. X
  53. Xtypedef struct {
  54. X
  55. X    char *basicfields[N_BASIC_FIELDS];
  56. X    int n_others;
  57. X    char **other_fields;
  58. X
  59. X  } Rolo_Entry, *Ptr_Rolo_Entry;
  60. X
  61. X  
  62. X#define get_basic_rolo_field(n,x) (((x) -> basicfields)[(n)])
  63. X#define get_n_others(x) ((x) -> n_others)  
  64. X#define get_other_field(n,x) (((x) -> other_fields)[n])
  65. X  
  66. X#define set_basic_rolo_field(n,x,s) (((x) -> basicfields[(n)]) = (s))
  67. X#define set_n_others(x,n) (((x) -> n_others) = (n))
  68. X#define incr_n_others(x) (((x) -> n_others)++)
  69. X#define set_other_field(n,x,s) ((((x) -> other_fields)[n]) = (s))
  70. X
  71. Xtypedef struct link {
  72. X
  73. X#ifndef VMS
  74. X    Ptr_Rolo_Entry entry;
  75. X#else
  76. X    Ptr_Rolo_Entry ventry;
  77. X#endif
  78. X    int matched;
  79. X    struct link *prev;
  80. X#ifndef M_V7
  81. X    struct link *next;
  82. X#else
  83. X    struct link *lnext;
  84. X#endif
  85. X
  86. X  } Rolo_List, *Ptr_Rolo_List;
  87. X
  88. X
  89. X#ifndef M_V7
  90. X#define get_next_link(x) ((x) -> next)
  91. X#else
  92. X#define get_next_link(x) ((x) -> lnext)
  93. X#endif
  94. X#define get_prev_link(x) ((x) -> prev)
  95. X#ifndef VMS
  96. X#define get_entry(x)     ((x) -> entry)
  97. X#else
  98. X#define get_entry(x)     ((x) -> ventry)
  99. X#endif
  100. X#define get_matched(x) ((x) -> matched)
  101. X
  102. X#ifndef M_V7
  103. X#define set_next_link(x,y) (((x) -> next) = (y))
  104. X#else
  105. X#define set_next_link(x,y) (((x) -> lnext) = (y))
  106. X#endif
  107. X#define set_prev_link(x,y) (((x) -> prev) = (y))
  108. X#ifndef VMS
  109. X#define set_entry(x,y) (((x) -> entry) = (y))
  110. X#else
  111. X#define set_entry(x,y) (((x) -> ventry) = (y))
  112. X#endif
  113. X#define set_matched(x) (((x) -> matched) = 1)
  114. X#define unset_matched(x) (((x) -> matched) = 0);
  115. X
  116. Xextern Ptr_Rolo_List Begin_Rlist;
  117. Xextern Ptr_Rolo_List End_Rlist;
  118. X
  119. X#define MAXLINELEN 80
  120. X#define DIRPATHLEN 100
  121. X
  122. Xextern int changed;
  123. Xextern int name_changed;
  124. Xextern int reorder_file;
  125. Xextern int rololocked;
  126. Xextern int read_only;
  127. X
  128. Xextern char *rolo_emalloc();
  129. Xextern char *malloc();
  130. Xextern Ptr_Rolo_List new_link_with_entry();
  131. Xextern char *copystr();
  132. Xextern int compare_links();
  133. Xextern char *timestring();
  134. Xextern char *homedir(), *libdir();
  135. Xextern char *getenv();
  136. Xextern char *ctime();
  137. Xextern char *select_search_string();
  138. Xextern int in_search_mode;
  139. X
  140. X/*
  141. X * This structure allows documentation and internal access to help files
  142. X */
  143. Xextern char *hlpfiles[];
  144. END_OF_FILE
  145. if test 2603 -ne `wc -c <'./datadef.h'`; then
  146.     echo shar: \"'./datadef.h'\" unpacked with wrong size!
  147. fi
  148. # end of './datadef.h'
  149. fi
  150. if test -f './options.c' -a "${1}" != "-c" ; then 
  151.   echo shar: Will not clobber existing file \"'./options.c'\"
  152. else
  153. echo shar: Extracting \"'./options.c'\" \(7034 characters\)
  154. sed "s/^X//" >'./options.c' <<'END_OF_FILE'
  155. X/* options.c */
  156. X#ifdef UNIX
  157. X#include <sys/types.h>
  158. X#include <time.h>
  159. X#ifdef BSD
  160. X#include <sys/file.h>
  161. X#include <sgtty.h>
  162. X#else
  163. X#include <fcntl.h>
  164. X#endif
  165. X#endif
  166. X
  167. X#ifdef VMS
  168. X#include <types.h>
  169. X#include <time.h>
  170. X#include <file.h>
  171. X#endif
  172. X
  173. X#ifdef MSDOS
  174. X#include <time.h>
  175. X#include <fcntl.h>
  176. X#endif
  177. X
  178. X#include <stdio.h>
  179. X#include <ctype.h>
  180. X
  181. X#include <signal.h>
  182. X
  183. X#ifdef TMC
  184. X#include <ctools.h>
  185. X#else
  186. X#include "ctools.h"
  187. X#endif
  188. X#include "args.h"
  189. X#include "menu.h"
  190. X#include "mem.h"
  191. X
  192. X#include "rolofilz.h"
  193. X#include "rolodefs.h"
  194. X#include "datadef.h"
  195. X#include "choices.h"
  196. X
  197. X
  198. Xprint_short ()
  199. X
  200. X/* print the names and phone numbers of everyone in the rolodex. */
  201. X
  202. X{ 
  203. X
  204. X  Ptr_Rolo_List rptr;
  205. X  Ptr_Rolo_Entry lentry;
  206. X        
  207. X  rptr = Begin_Rlist;
  208. X  if (rptr == 0) {
  209. X     fprintf(stderr,"No entries to print out...\n");
  210. X     return;
  211. X  }
  212. X   
  213. X  fprintf (
  214. X     stdout,
  215. X     "\nNAME                      WORK PHONE                HOME PHONE"
  216. X   );
  217. X  fprintf (
  218. X     stdout,
  219. X     "\n----                      ----------                ----------\n\n\n"
  220. X   );
  221. X
  222. X   while (rptr != 0) {
  223. X        lentry = get_entry(rptr);
  224. X        fprintf (
  225. X            stdout,
  226. X            "%-25s %-25s %-25s\n",
  227. X            get_basic_rolo_field((int) R_NAME,lentry),
  228. X            get_basic_rolo_field((int) R_WORK_PHONE,lentry),
  229. X            get_basic_rolo_field((int) R_HOME_PHONE,lentry)
  230. X         );   
  231. X         rptr = get_next_link(rptr);
  232. X   }       
  233. X   
  234. X }  
  235. X   
  236. X
  237. Xperson_match (person,lentry) char *person; Ptr_Rolo_Entry lentry; 
  238. X/* Match against a rolodex entry's Name and Company fields. */
  239. X/* Thus if I say 'rolo CCA' I will find people who work at CCA. */
  240. X/* This is good because sometimes you will forget a name but remember */
  241. X/* the company the person works for. */
  242. X
  243. X{ 
  244. X  char *name, *company;        
  245. X  int len;
  246. X  len = strlen(person);
  247. X  name = get_basic_rolo_field((int) R_NAME,lentry);
  248. X  company = get_basic_rolo_field((int) R_COMPANY,lentry);
  249. X  if (strncsearch(name,strlen(name),person,len)) return(1);
  250. X  if (strncsearch(company,strlen(company),person,len)) return(1);
  251. X  return(0);
  252. X}
  253. X
  254. Xint find_all_person_matches (person) char *person;
  255. X
  256. X{
  257. X  Ptr_Rolo_List rptr = Begin_Rlist;        
  258. X  int count = 0;
  259. X  while (rptr != 0) {
  260. X    unset_matched(rptr);
  261. X    if (person_match(person,get_entry(rptr))) {
  262. X       set_matched(rptr);
  263. X       count++;
  264. X    }
  265. X    rptr = get_next_link(rptr);
  266. X  }
  267. X  return(count);
  268. X}
  269. X
  270. X
  271. Xlook_for_person (person) char *person; 
  272. X
  273. X/* search against Name and Company over the rolodex.  If a match is found */
  274. X/* display the entry and give the user a choice of what to do next. */
  275. X
  276. X{
  277. X  Ptr_Rolo_List rptr;        
  278. X  int found = 0,result,nmatches;
  279. X  static displayed_menu = 0;
  280. X  char *response;
  281. X  
  282. X  rptr = Begin_Rlist;        
  283. X  while (rptr != 0) {        
  284. X    if (person_match(person,get_entry(rptr))) {
  285. X       clear_the_screen();
  286. X       display_entry(get_entry(rptr));
  287. X       if (!found) {
  288. X          nmatches = find_all_person_matches(person);
  289. X          if (nmatches > 1) {
  290. X             printf (
  291. X                "There are %d other entries which match '%s'\n\n",
  292. X                nmatches - 1, person
  293. X              );
  294. X          }
  295. X       }
  296. X       found = 1;
  297. X       try_again :
  298. X       if (!displayed_menu) cathelpfile(POPTIONMENU,(char *)NULL,0);
  299. X       displayed_menu = 1;
  300. X       menu_match (
  301. X            &result,
  302. X            &response,
  303. X            "Select option (? for help): ",
  304. X            0,1,1,1,6,
  305. X            "Continue",P_CONTINUE,
  306. X            "",P_CONTINUE,
  307. X            "Next",P_NEXT_PERSON,
  308. X            "\\",P_ABORT,
  309. X            "Help",P_HELP,
  310. X            "?",P_HELP
  311. X         );
  312. X       switch (result) {
  313. X         case P_CONTINUE :
  314. X           break;
  315. X         case P_NEXT_PERSON :
  316. X           return(0);
  317. X           /* break; */
  318. X         case P_ABORT :
  319. X           roloexit(0);
  320. X           break;
  321. X         case P_HELP :
  322. X           cathelpfile(POPTIONSHELP,"person search options",1);
  323. X           goto try_again;
  324. X         default :
  325. X           fprintf(stderr,"Impossible return from menu_match\n");
  326. X           exit(-1);
  327. X       }
  328. X    }
  329. X    rptr = get_next_link(rptr);
  330. X  }
  331. X  if (!found) {
  332. X     fprintf(stderr,"\nNo entry found for '%s'\n\n",person);
  333. X     sleep(2);
  334. X  }
  335. X  else {
  336. X     printf("No further matches for '%s'\n",person);
  337. X     sleep(2);
  338. X  }   
  339. X  return(0);
  340. X}
  341. Xprint_people ()
  342. X
  343. X{
  344. X  int index;
  345. X  char *person;
  346. X  index = 1;
  347. X  while (T) {
  348. X     if (0 == (person = non_option_arg(index++))) break;
  349. X     look_for_person(person);
  350. X  }
  351. X}
  352. X
  353. X
  354. Xinteractive_rolo ()
  355. X
  356. X/* Top level of the iteractive rolodex.  This code is just a big switch */
  357. X/* which passes responsibility off to various routines in 'operatns.c' */
  358. X/* and 'update.c' */
  359. X
  360. X{
  361. X
  362. X  int result,rval,field_index;
  363. X  char *response,*field_name,*search_string;
  364. X
  365. X  fprintf(stdout,"\n\nTMC ROLODEX, Version %s\n\n\n",VERSION);        
  366. X  
  367. X  while (1) {        
  368. X        
  369. X    cathelpfile(MAINMENU,(char *)NULL,0);
  370. X    rval = menu_match (
  371. X         &result,
  372. X         &response,
  373. X         "Select option (? for help): ",
  374. X         0,1,0,1,7,
  375. X         "+",M_ADD,
  376. X         "%",M_PERUSE,
  377. X         "\\",M_EXIT,
  378. X         "?",M_HELP,
  379. X         "*",M_SAVE,
  380. X         "$",M_SEARCH_BY_OTHER,
  381. X         "!",M_PRINT_TO_LASER_PRINTER
  382. X      );
  383. X      
  384. X    switch (rval) {
  385. X        
  386. X      case MENU_AMBIGUOUS :
  387. X      case MENU_ERROR :
  388. X        fprintf(stderr,"Impossible return 1 from main menu_match\n");
  389. X        exit(-1);
  390. X        break;
  391. X        
  392. X      case MENU_NO_MATCH :
  393. X        response = copystr(response);
  394. X        rolo_search_mode((int) R_NAME,Field_Names[(int) R_NAME],response);
  395. X        break;
  396. X        
  397. X      case MENU_MATCH :
  398. X        
  399. X        switch (result) {
  400. X          case M_ADD :
  401. X            rolo_add();
  402. X            break;
  403. X          case M_SEARCH_BY_OTHER :
  404. X            if ((-1 == select_field_to_search_by(&field_index,&field_name)) ||
  405. X                (0 == (search_string = select_search_string()))) {
  406. X               break;
  407. X            }
  408. X            rolo_search_mode(field_index,field_name,search_string);
  409. X            break;
  410. X          case M_PRINT_TO_LASER_PRINTER :
  411. X            /* fprintf(stderr,"Not implemented\n"); */
  412. X        pretty_print();
  413. X            sleep(1);
  414. X            break;
  415. X          case M_PERUSE :
  416. X            rolo_peruse_mode(Begin_Rlist);
  417. X            break;
  418. X          case M_EXIT :
  419. X            save_and_exit(0);
  420. X            break;
  421. X          case M_SAVE :
  422. X            if (changed) {
  423. X               save_to_disk();
  424. X               sleep(1);
  425. X            }
  426. X            else {
  427. X               printf("No changes to be saved...\n");
  428. X               sleep(2);
  429. X            }
  430. X            break;
  431. X          case M_HELP :
  432. X            cathelpfile(MOPTIONHELP,"top level menu",1);
  433. X            any_char_to_continue();
  434. X            break;
  435. X          default :
  436. X            fprintf(stderr,"Impossible result from menu_match...\n");
  437. X            save_and_exit(-1);
  438. X        }
  439. X        break;
  440. X            
  441. X      case MENU_EOF :
  442. X        user_eof();
  443. X        break;
  444. X        
  445. X      default :
  446. X        fprintf(stderr,"Impossible return 2 from menu_match\n");
  447. X        save_and_exit(-1);
  448. X        
  449. X    }
  450. X    
  451. X    clear_the_screen();
  452. X    
  453. X  }
  454. X
  455. X}
  456. END_OF_FILE
  457. if test 7034 -ne `wc -c <'./options.c'`; then
  458.     echo shar: \"'./options.c'\" unpacked with wrong size!
  459. fi
  460. # end of './options.c'
  461. fi
  462. if test -f './rlist.c' -a "${1}" != "-c" ; then 
  463.   echo shar: Will not clobber existing file \"'./rlist.c'\"
  464. else
  465. echo shar: Extracting \"'./rlist.c'\" \(2570 characters\)
  466. sed "s/^X//" >'./rlist.c' <<'END_OF_FILE'
  467. X/* rlist.c */
  468. X#include "datadef.h"
  469. X
  470. X
  471. Xint rlength (rlist) Ptr_Rolo_List rlist;
  472. X{
  473. X  return((rlist == 0) ? 0 : 1 + rlength(get_next_link(rlist)));
  474. X}  
  475. X  
  476. X
  477. XPtr_Rolo_List new_link_with_entry ()
  478. X{
  479. X  Ptr_Rolo_List newlink;        
  480. X  Ptr_Rolo_Entry newentry;
  481. X  newlink = (Ptr_Rolo_List) rolo_emalloc(sizeof(Rolo_List));
  482. X  unset_matched(newlink);
  483. X  newentry = (Ptr_Rolo_Entry) rolo_emalloc(sizeof(Rolo_Entry));
  484. X  set_n_others(newentry,0);        
  485. X  newentry -> other_fields = 0;
  486. X  set_entry(newlink,newentry);
  487. X  return(newlink);
  488. X}
  489. X
  490. X
  491. Xrolo_insert (link,compare) Ptr_Rolo_List link; int (*compare)();
  492. X
  493. X{
  494. X  Ptr_Rolo_List rptr;        
  495. X        
  496. X  if (Begin_Rlist == 0) {
  497. X     Begin_Rlist = link;
  498. X     End_Rlist = link;
  499. X     set_prev_link(link,0);
  500. X     set_next_link(link,0);
  501. X     return;
  502. X  }
  503. X  
  504. X  /* find the element it goes before, alphabetically, and insert it */
  505. X
  506. X  rptr = Begin_Rlist;
  507. X  while (rptr != 0) {
  508. X    if (1 == (*compare)(rptr,link)) {
  509. X       set_prev_link(link,get_prev_link(rptr));
  510. X       set_next_link(link,rptr);
  511. X       if (get_prev_link(rptr) != 0) 
  512. X          set_next_link(get_prev_link(rptr),link);
  513. X       else
  514. X          Begin_Rlist = link;
  515. X       set_prev_link(rptr,link);
  516. X       return;
  517. X    }
  518. X    rptr = get_next_link(rptr);
  519. X  }
  520. X
  521. X  /* it goes at the end */
  522. X  
  523. X  set_next_link(End_Rlist,link);
  524. X  set_prev_link(link,End_Rlist);
  525. X  set_next_link(link,0);
  526. X  End_Rlist = link;
  527. X  return;
  528. X
  529. X}
  530. X
  531. X
  532. Xrolo_delete (link) Ptr_Rolo_List link;
  533. X
  534. X{
  535. X  if (read_only)
  536. X  {
  537. X    printf("Readonly mode: Cannot delete entries.\n");
  538. X    sleep(2);
  539. X    return(1);
  540. X  }
  541. X
  542. X  if (get_next_link(link) == 0 && get_prev_link(link) == 0) {
  543. X     Begin_Rlist = 0;
  544. X     End_Rlist = 0;
  545. X     return(0);
  546. X  }
  547. X
  548. X  if (get_prev_link(link) == 0) {
  549. X     Begin_Rlist = get_next_link(link);
  550. X     set_prev_link(Begin_Rlist,0);
  551. X     return(0);
  552. X  }
  553. X
  554. X  if (get_next_link(link) == 0) {
  555. X     End_Rlist = get_prev_link(link);
  556. X     set_next_link(End_Rlist,0);
  557. X     return(0);
  558. X  }
  559. X
  560. X  set_next_link(get_prev_link(link),get_next_link(link));
  561. X  set_prev_link(get_next_link(link),get_prev_link(link));
  562. X  return(0);
  563. X
  564. X}
  565. X
  566. X
  567. Xcompare_links (l1,l2) Ptr_Rolo_List l1,l2;
  568. X
  569. X{
  570. X  Ptr_Rolo_Entry e1,e2;        
  571. X  char *n1,*n2;
  572. X  e1 = get_entry(l1);        
  573. X  e2 = get_entry(l2);        
  574. X  n1 = get_basic_rolo_field((int) R_NAME,e1);
  575. X  n2 = get_basic_rolo_field((int) R_NAME,e2);
  576. X  return(nocase_compare(n1,strlen(n1),n2,strlen(n2)));
  577. X}  
  578. X  
  579. X
  580. Xrolo_reorder ()
  581. X{
  582. X  Ptr_Rolo_List rptr,oldlink;
  583. X  rptr = Begin_Rlist;
  584. X  Begin_Rlist = 0;
  585. X  while (rptr != 0) {
  586. X    oldlink = get_next_link(rptr);
  587. X    rolo_insert(rptr,compare_links);
  588. X    rptr = oldlink;
  589. X  }
  590. X}
  591. END_OF_FILE
  592. if test 2570 -ne `wc -c <'./rlist.c'`; then
  593.     echo shar: \"'./rlist.c'\" unpacked with wrong size!
  594. fi
  595. # end of './rlist.c'
  596. fi
  597. if test -f './rolo.1' -a "${1}" != "-c" ; then 
  598.   echo shar: Will not clobber existing file \"'./rolo.1'\"
  599. else
  600. echo shar: Extracting \"'./rolo.1'\" \(2616 characters\)
  601. sed "s/^X//" >'./rolo.1' <<'END_OF_FILE'
  602. X.TH ROLO 1 "18 November 1984"
  603. X.UC 4
  604. X.SH NAME
  605. Xrolo \- use an online rolodex, containing information about people.
  606. X.SH SYNOPSIS
  607. X.B rolo
  608. X[ name1 name2 ... \-u otheruser \-s \-l \-r ]
  609. X.SH DESCRIPTION
  610. XBy default
  611. X.I rolo
  612. Xreads in a rolodex data file from the user's home directory, prints
  613. Xout a menu of choices, and lets the user scan, update, delete and add to
  614. Xhis personal database of people.  If no rolodex database exists one
  615. Xis created.
  616. X.I rolo
  617. Xchecks to see that the rolodex database is not already in use.
  618. X.PP
  619. XThe command line options are:
  620. X.TP
  621. X.B \-u otheruser
  622. XUses the rolodex database in the 'otheruser' home directory.  This may
  623. Xnot be possible if the directory or the database is read or write protected.
  624. XFor VMS or DOS, it will simply use files found in directory 'otheruser';
  625. Xthis need not be the home directory.
  626. X.TP
  627. X.B \-s
  628. XPrints people's names, work phone numbers and home phone numbers in a nice
  629. Xformat to standard output.
  630. X.TP
  631. X.B \-l
  632. XNormally the rolodex database is locked when being used.  This option
  633. Xunlocks the database as soon as it is read in.  The \-s option implies this.
  634. X.TP
  635. X.B \-r
  636. XReadonly mode.  Assuming that the files may be read, this allows readonly
  637. Xaccess to the database.
  638. X.PP
  639. XInvoking 
  640. X.I rolo
  641. Xfollowed by a list of names causes 
  642. X.I
  643. Xrolo
  644. Xto search the database for all people whose names or company
  645. Xaffiliations contain any of the name arguments as substrings.  All the
  646. Xinformation about each person is printed to standard output, the program
  647. Xpausing after each record is printed.  Using this feature causes the
  648. Xdatabase to become unlocked, since this is a read-only mode.
  649. X.PP
  650. XExtensive help is available on-line.  Typing '?' or 'help' will generally
  651. Xprint a help file for you.
  652. X.SH FILES
  653. X/usr/local/src/rolo     for the source.
  654. X.PP
  655. X/usr/local/lib/rolo     for help files.
  656. X.PP
  657. X/usr/local/bin/rolo     the executable image.
  658. X.PP
  659. X.PP
  660. X.SH AUTHOR
  661. XPeter Webb wrote the first rolodex program.
  662. X.PP
  663. XJP Massar revised and then complete rewrote this older version.
  664. XNet address: massar@think.com, ihnp4!think!massar.
  665. X.PP
  666. XDave Ihnat revised the program to work for VMS and MS/PC-DOS; and to support
  667. Xthe readonly command-line flag.  Numerous other minor enhancements, bug fixes,
  668. Xdelinting, etc.
  669. XNet address: ihnp4!homebru!ignatz.
  670. X
  671. X.PP
  672. XSteve Steiner implemented the pretty-print option, and with Dave Ihnat hammered
  673. Xout the current version which runs on VMS, AT&T Unix Sys III/V, BSD 4.x Unix,
  674. Xand MS/PC-DOS under Microsoft C and Turbo-C. (*whew!*)
  675. XNet address: ihnp4!aicchi!steiner.
  676. X.SH BUGS
  677. XThere is no way to keep certain entries private.
  678. X.PP
  679. XYou can't get a short summary of only a subset of people.
  680. END_OF_FILE
  681. if test 2616 -ne `wc -c <'./rolo.1'`; then
  682.     echo shar: \"'./rolo.1'\" unpacked with wrong size!
  683. fi
  684. # end of './rolo.1'
  685. fi
  686. if test -f './search.c' -a "${1}" != "-c" ; then 
  687.   echo shar: Will not clobber existing file \"'./search.c'\"
  688. else
  689. echo shar: Extracting \"'./search.c'\" \(9196 characters\)
  690. sed "s/^X//" >'./search.c' <<'END_OF_FILE'
  691. X/* search.c */
  692. X#include <stdio.h>
  693. X#include <ctype.h>
  694. X
  695. X#ifdef TMC
  696. X#include <ctools.h>
  697. X#else
  698. X#include "ctools.h"
  699. X#endif
  700. X#include "args.h"
  701. X#include "menu.h"
  702. X#include "mem.h"
  703. X
  704. X#include "rolofilz.h"
  705. X#include "rolodefs.h"
  706. X#include "datadef.h"
  707. X#include "choices.h"
  708. X
  709. X
  710. Xchar *select_search_string ()
  711. X
  712. X/* returns 0 if user wants to quit, otherwise returns a user-provided string */
  713. X
  714. X{
  715. X  int rval;        
  716. X  char *response;
  717. X  rval = rolo_menu_data_help_or_abort (        
  718. X              "Enter string to search for: ",
  719. X              SEARCHSTRINGHELP,
  720. X              "string to search for",
  721. X              &response
  722. X          );
  723. X  switch (rval) {          
  724. X    case MENU_ABORT :
  725. X      return(0);
  726. X      /* break; */
  727. X    case MENU_DATA :
  728. X      return(copystr(response));
  729. X      /* break; */
  730. X  }
  731. X
  732. X  return(0);
  733. X}  
  734. X  
  735. X
  736. Xselect_field_to_search_by (ptr_index,ptr_name) int *ptr_index; char **ptr_name;
  737. X
  738. X/* returns -1 if the user wishes to abort, otherwise returns 0. */
  739. X/* if the user wishes to search by a user-defined field, *ptr_index is OTHER */
  740. X/* and *ptr_name is the user-provided name of the field. */
  741. X
  742. X{
  743. X  char *response;
  744. X  int nchoices = N_BASIC_FIELDS;
  745. X  int field_index,rval;
  746. X  
  747. X  redo :
  748. X  
  749. X  /* list out each basic field that the user can search by.   The user is */
  750. X  /* also given an option to search by a user-provided field.   At the */
  751. X  /* moment you cannot search by 'Date Updated' */
  752. X  
  753. X  display_field_names();  
  754. X  
  755. X  /* reask : */
  756. X  
  757. X  rval = rolo_menu_number_help_or_abort (
  758. X       "Number of item to search by? ",
  759. X       1,nchoices,&field_index
  760. X    );
  761. X    
  762. X  switch (rval) {
  763. X        
  764. X    case MENU_ABORT :
  765. X      return(-1);
  766. X      /* break; */
  767. X      
  768. X    case MENU_HELP :
  769. X      cathelpfile(FIELDSEARCHHELP,"entering search field",1);
  770. X      any_char_to_continue();
  771. X      goto redo;
  772. X      /* break; */
  773. X      
  774. X    case MENU_DATA :
  775. X    
  776. X      if (field_index != nchoices) {
  777. X         *ptr_index = field_index - 1;
  778. X         *ptr_name = copystr(Field_Names[*ptr_index]);
  779. X         return(0);
  780. X      }
  781. X      
  782. X      /* the user wants to search by a user-specified field */
  783. X      
  784. X      else {
  785. X        
  786. X         /* reask2 : */
  787. X        
  788. X         rval = rolo_menu_data_help_or_abort (
  789. X                    "Name of user-defined field? ",
  790. X                    USERFIELDHELP,
  791. X                    "name of user field to search by",
  792. X                    &response
  793. X                 );
  794. X         switch (rval) {
  795. X           case MENU_ABORT :
  796. X             return(-1);
  797. X             /* break; */
  798. X           case MENU_DATA :
  799. X             *ptr_index = OTHER;
  800. X             *ptr_name = copystr(response);           
  801. X             return(0);         
  802. X             /* break; */
  803. X         }
  804. X      }
  805. X      break;
  806. X  }
  807. X  return(0);
  808. X}  
  809. X      
  810. X
  811. Xmatch_by_name_or_company (search_string,sslen) char *search_string; int sslen;
  812. X
  813. X{
  814. X  char *name,*company;
  815. X  Ptr_Rolo_Entry lentry;        
  816. X  Ptr_Rolo_List rlist;
  817. X  int count = 0;
  818. X  
  819. X  rlist = Begin_Rlist;
  820. X  while (rlist != 0) {  
  821. X    lentry = get_entry(rlist);
  822. X    name = get_basic_rolo_field((int) R_NAME,lentry);
  823. X    company = get_basic_rolo_field((int) R_COMPANY,lentry);
  824. X    if (strncsearch(name,strlen(name),search_string,sslen) ||
  825. X        strncsearch(company,strlen(company),search_string,sslen)) {
  826. X       set_matched(rlist);
  827. X       count++;
  828. X    }
  829. X  }
  830. X  return(count);
  831. X  
  832. X}
  833. X
  834. X
  835. Xmatch_link (rlink,field_index,field_name,fnlen,search_string,sslen)
  836. X
  837. X  /* if a match is present, sets the 'matched' field in the link, and */
  838. X  /* returns 1, otherwise returns 0. */
  839. X
  840. X  Ptr_Rolo_List rlink;
  841. X  int field_index;
  842. X  char *field_name;
  843. X  int fnlen;
  844. X  char *search_string;
  845. X  int sslen;
  846. X  
  847. X{
  848. X  Ptr_Rolo_Entry lentry;        
  849. X  char *field;
  850. X  char name[100];
  851. X  int j;
  852. X        
  853. X  lentry = get_entry(rlink);
  854. X  
  855. X  if (field_index == OTHER) {
  856. X     for (j = 0; j < get_n_others(lentry); j++) {
  857. X         field = get_other_field(j,lentry);
  858. X         while (*field != ':') *field++;
  859. X         *field = '\0';
  860. X         remove_excess_blanks(name,get_other_field(j,lentry));
  861. X         *field++ = ':';
  862. X         if (0 != nocase_compare(name,strlen(name),field_name,fnlen)) {
  863. X            continue;
  864. X         }
  865. X         if (strncsearch(field,strlen(field),search_string,sslen)) {
  866. X            set_matched(rlink);
  867. X            return(1);
  868. X         }
  869. X     }
  870. X     return(0);
  871. X  }
  872. X  else {
  873. X     field = get_basic_rolo_field(field_index,lentry);
  874. X     if (strncsearch(field,strlen(field),search_string,sslen)) {
  875. X        set_matched(rlink);
  876. X        return(1);
  877. X     }
  878. X     return(0);
  879. X  }
  880. X
  881. X}
  882. X
  883. X
  884. Xfind_all_matches (field_index,field_name,search_string,ptr_first_match) 
  885. X
  886. X  /* mark every entry in the rolodex which matches against the search_string */
  887. X  /* If the search_string is a substring of the data in the given field then */
  888. X  /* that is a match.  Return the number of matches.  If there are any */
  889. X  /* matches *ptr_first_match will contain the first matching link. */
  890. X
  891. X  int field_index;
  892. X  char *field_name, *search_string;
  893. X  Ptr_Rolo_List *ptr_first_match;
  894. X
  895. X{  
  896. X  char buffer[100];    
  897. X  int fnlen,sslen;
  898. X  int count = 0;
  899. X  Ptr_Rolo_List rlist = Begin_Rlist;
  900. X  
  901. X  remove_excess_blanks(buffer,field_name);
  902. X  fnlen = strlen(buffer);
  903. X  sslen = strlen(search_string);
  904. X  
  905. X  while (rlist != 0) {  
  906. X    unset_matched(rlist);
  907. X    if (match_link(rlist,field_index,buffer,fnlen,search_string,sslen)) {
  908. X       if (count++ == 0) *ptr_first_match = rlist;
  909. X    }
  910. X    rlist = get_next_link(rlist);
  911. X  }    
  912. X  
  913. X  return(count);
  914. X  
  915. X}
  916. X
  917. X
  918. Xrolo_search_mode (field_index,field_name,search_string)
  919. X
  920. X  int field_index;
  921. X  char *field_name;
  922. X  char *search_string;
  923. X
  924. X{
  925. X  int rval,n,j,menuval,ival;
  926. X  char *response;
  927. X  Ptr_Rolo_List first_match,rmatch,rlist;
  928. X
  929. X  /* mark every entry in the rolodex that satisfies the search criteria */
  930. X  /* and return the number of items so marked. */
  931. X  
  932. X  in_search_mode = 1;
  933. X  n = find_all_matches(field_index,field_name,search_string,&first_match);
  934. X
  935. X  if (n == 0) {
  936. X     printf (
  937. X         "No match found for search string '%s' for field '%s'\n",
  938. X         search_string,
  939. X         field_name
  940. X      );
  941. X      sleep(2);
  942. X      goto rtn;
  943. X  }
  944. X
  945. X  /* if the match is unique, just display the entry. */
  946. X  
  947. X  else if (n == 1) {
  948. X     display_entry(get_entry(first_match));
  949. X     switch (entry_action(first_match)) {
  950. X       case E_CONTINUE :
  951. X         printf("No further matches...\n");
  952. X         sleep(2);
  953. X         break;
  954. X       default :
  955. X         break;
  956. X     }
  957. X     goto rtn;
  958. X  }
  959. X
  960. X  /* if there are too many matches to itemize them on a single small */
  961. X  /* screen, tell the user that there are lots of matches and suggest */
  962. X  /* he specify a better search string, but give him the option of */
  963. X  /* iterating through every match. */
  964. X  
  965. X  else if (n > MAXMATCHES) {
  966. X     clear_the_screen();
  967. X     printf("There are %d entries that match '%s' !\n",n,search_string);
  968. X     printf("Type 'v' to view them one by one,\n");
  969. X     printf("or '\\' to abort and enter a more specific search string: ");
  970. X     rval = rolo_menu_data_help_or_abort (
  971. X                 "",MANYMATCHHELP,"many matching entries",&response
  972. X              );
  973. X     if (rval == MENU_ABORT) goto rtn;              
  974. X     display_list_of_entries(Begin_Rlist);
  975. X     goto rtn;
  976. X  }
  977. X
  978. X  /* there are a small number of matching entries.  List the name of each */
  979. X  /* matching entry and let the user select which one he wants to view, */
  980. X  /* or whether he wants to iterate through each matching entry. */
  981. X  
  982. X  else {
  983. X     relist :
  984. X     summarize_entry_list(Begin_Rlist,search_string);
  985. X     cathelpfile(PICKENTRYMENU,(char *)NULL,0);  
  986. X     rval = menu_match (
  987. X          &menuval,&response,
  988. X          ": ",
  989. X          0,1,0,1,4,
  990. X          "\\",S_ABORT,
  991. X          "?",S_HELP,
  992. X          "Help",S_HELP,
  993. X          "",S_SCAN_ONE_BY_ONE
  994. X       );
  995. X     switch (rval) {    
  996. X       case MENU_MATCH :
  997. X         switch (menuval) {
  998. X           case S_HELP :
  999. X             cathelpfile(PICKENTRYHELP,"selecting entry to view",1);
  1000. X             any_char_to_continue();
  1001. X             goto relist;
  1002. X             /* break; */
  1003. X           case S_ABORT :
  1004. X             goto rtn;
  1005. X             /* break; */
  1006. X           case S_SCAN_ONE_BY_ONE :
  1007. X             display_list_of_entries(Begin_Rlist);
  1008. X             goto rtn;
  1009. X             /* break; */
  1010. X         }
  1011. X         break;
  1012. X         
  1013. X       /* make sure the user entered a valid integer, ival */
  1014. X       /* if so, find the ivalth entry marked as matched in the rolodex */
  1015. X       /* and display it. */
  1016. X         
  1017. X       case MENU_NO_MATCH : 
  1018. X         ival = str_to_pos_int(response,1,n);
  1019. X         if (ival < 0) {
  1020. X            printf("Not a valid number... Please try again\n");
  1021. X            sleep(2);
  1022. X            goto relist;
  1023. X         }
  1024. X         rlist = Begin_Rlist;
  1025. X         for (j = 0; j < ival; j++) {
  1026. X             while (rlist != 0) {
  1027. X               if (get_matched(rmatch = rlist)) break;
  1028. X               rlist = get_next_link(rlist);
  1029. X             }
  1030. X             if (rlist != 0) rlist = get_next_link(rlist);                
  1031. X         }
  1032. X         display_entry(get_entry(rmatch));
  1033. X         switch (entry_action(rmatch)) {
  1034. X           case E_CONTINUE :
  1035. X           case E_PREV :
  1036. X             goto relist;
  1037. X             /* break; */
  1038. X           default :
  1039. X             goto rtn;
  1040. X             /* break; */
  1041. X         }
  1042. X         /* break; */
  1043. X     }
  1044. X  }
  1045. X
  1046. X  rtn :
  1047. X  in_search_mode = 0;
  1048. X  
  1049. X}
  1050. END_OF_FILE
  1051. if test 9196 -ne `wc -c <'./search.c'`; then
  1052.     echo shar: \"'./search.c'\" unpacked with wrong size!
  1053. fi
  1054. # end of './search.c'
  1055. fi
  1056. if test -f './toolsdir/args.c' -a "${1}" != "-c" ; then 
  1057.   echo shar: Will not clobber existing file \"'./toolsdir/args.c'\"
  1058. else
  1059. echo shar: Extracting \"'./toolsdir/args.c'\" \(9032 characters\)
  1060. sed "s/^X//" >'./toolsdir/args.c' <<'END_OF_FILE'
  1061. X#include <stdio.h>
  1062. X#include <ctype.h>
  1063. X#include "basics.h"
  1064. X#include "args.h"        
  1065. X#include "sys5.h"
  1066. X
  1067. X/***************************************************************************/
  1068. X/***************************************************************************/
  1069. X
  1070. X           /*****     COMMAND LINE ARGUMENT PARSER    *****/
  1071. X
  1072. X/***************************************************************************/
  1073. X/***************************************************************************/
  1074. X
  1075. X/* Author: JP Massar */
  1076. X
  1077. X/* parses command line arguments in argv under the following rules: */
  1078. X/* any argument not beginning with '-' is treated as a unit. */
  1079. X/* any argument beginning with a '-' must have the remaining characters */
  1080. X/* be in the set {a-zA-Z}.  Each character is considered a separate option. */
  1081. X/* (Thus -abc is equivalent to -a -b -c).  Non-dashed arguments are */
  1082. X/* associated with the option that precedes them, e.g, 'cat -a foo -b bar' */
  1083. X/* has foo associated with 'a' and bar associated with 'b'.  A non-dashed */
  1084. X/* argument preceding any option is not associated with any option. */
  1085. X/* users can specify whether duplicate options are errors. */
  1086. X
  1087. X/* Non-dashed arguments are henceforth referred to as arguments, and */
  1088. X/* dashed arguments are henceforth referred to as options. */
  1089. X/* Arguments are ordered from left to right. */
  1090. X
  1091. X/* 5/8/87 - D. M. Ihnat.  Modified for DOS/VMS to honor '/' as a separator.
  1092. X*/
  1093. X/* The following routines are available to users: */
  1094. X
  1095. X/* get_args()           called to parse argv.  Detects syntactic errors */
  1096. X/* any_option_present() are any options present in the command line? */
  1097. X/* option_present()     is an option present? */
  1098. X/* option_arg()         returns an argument associated with an option */
  1099. X/* non_option_arg()     returns an argument not associated with any option */
  1100. X/* non_dash_arg()       returns an argument */
  1101. X/* n_option_args()      returns number of args associated with an option */
  1102. X/* n_non_option_args()  rtns number of args not associated with any option */
  1103. X/* n_non_dash_args()    returns number of arguments. */
  1104. X/* check_option_args()  checks bounds on number of args assoc with an option */
  1105. X/* legal_options()      checks that options provided are a subset of a-zA-Z */
  1106. X/* set_option()         turns on option */
  1107. X/* error_message()      prints out an illegal syntax error message to stderr */
  1108. X
  1109. X
  1110. Xint option_to_index (achar) char achar;
  1111. X{
  1112. X  if (isupper(achar)) return(achar - 'A');
  1113. X  if (islower(achar)) return(achar - 'a' + 26);
  1114. X  return(NO_OPTION);
  1115. X}
  1116. X
  1117. Xchar index_to_option (index) int index;
  1118. X{        
  1119. X  if (index < 26) return('A' + index);
  1120. X  return('a' + index - 26);
  1121. X}  
  1122. X
  1123. X
  1124. X/* the command line arguments are parsed into Cmd when get_args returns */
  1125. X/* successfully */
  1126. X
  1127. Xstatic Ptr_Cmd_Line Cmd = NIL;
  1128. X
  1129. Xint get_args (argc, argv, dup_error, print_msg)
  1130. X        
  1131. X  /* Returns one of NO_ARGS, ARG_ERROR, or ARGS_PRESENT */
  1132. X
  1133. X  int argc;
  1134. X  char **argv;
  1135. X  Bool print_msg, dup_error;
  1136. X
  1137. X{
  1138. X  int i,j,dash_index;
  1139. X  Ptr_Cmd_Arg arg,last = NIL;
  1140. X  char echar, *optr;
  1141. X
  1142. X  Cmd = (Ptr_Cmd_Line) malloc(sizeof(Cmd_Line));
  1143. X  Cmd -> non_dash_arg_list = NIL;
  1144. X  for (j = 0; j < MAX_OPTIONS; j++) (Cmd -> dash_options)[j] = F;
  1145. X
  1146. X  if (argc == 1) return(NO_ARGS);
  1147. X
  1148. X  i = 0;
  1149. X  dash_index = NO_OPTION;
  1150. X  
  1151. X  while (++i < argc) {
  1152. X        
  1153. X        /* parse arguments (i.e., anything not beginning with '-' */
  1154. X
  1155. X#ifdef UNIX        
  1156. X        if (argv[i][0] != '-') {
  1157. X#endif
  1158. X#ifdef VMS
  1159. X    if ((argv[i][0] != '/') && (argv[i][0] != '-')) {
  1160. X#endif
  1161. X#ifdef MSDOS
  1162. X    if ((argv[i][0] != '/') && (argv[i][0] != '-')) {
  1163. X#endif
  1164. X                arg = (Ptr_Cmd_Arg) malloc(sizeof(Cmd_Arg));
  1165. X                arg -> option = argv[i];
  1166. X                arg -> option_index = dash_index;
  1167. X                arg -> next = NIL;
  1168. X                if (last == NIL) {
  1169. X                        Cmd -> non_dash_arg_list = arg;
  1170. X                        last = arg;
  1171. X                }                
  1172. X                else {
  1173. X                        last -> next = arg;
  1174. X                        last = arg;
  1175. X                }
  1176. X                continue;
  1177. X        }
  1178. X
  1179. X        /* parse options. '-' by itself is illegal syntax */
  1180. X        
  1181. X        if (strlen(argv[i]) < 2) {
  1182. X#ifdef UNIX
  1183. X                echar = '-';
  1184. X#endif
  1185. X#ifdef VMS
  1186. X                echar = '/';
  1187. X#endif
  1188. X#ifdef MSDOS
  1189. X                echar = '/';
  1190. X#endif
  1191. X                goto parse_error;
  1192. X        }        
  1193. X        optr = argv[i];
  1194. X        optr++;
  1195. X        while (*optr != '\0') {
  1196. X                if (NO_OPTION == (dash_index = option_to_index(*optr))) {
  1197. X                        echar = *optr;
  1198. X                        goto parse_error;
  1199. X                };
  1200. X                if ((Cmd -> dash_options)[dash_index] && dup_error) {
  1201. X                        echar = *optr;
  1202. X                        goto duplicate_error;
  1203. X                }
  1204. X                (Cmd -> dash_options)[dash_index] = T;
  1205. X                optr++;
  1206. X        }
  1207. X
  1208. X  }                              
  1209. X
  1210. X  return(ARGS_PRESENT);
  1211. X
  1212. X  parse_error :
  1213. X
  1214. X  if (print_msg) fprintf(stderr,"illegal option: %c\n",echar);
  1215. X  return(ARG_ERROR);
  1216. X
  1217. X  duplicate_error:
  1218. X
  1219. X  if (print_msg) fprintf(stderr,"duplicate option: %c\n",echar);
  1220. X  return(ARG_ERROR);
  1221. X
  1222. X}  
  1223. X
  1224. X                          
  1225. XBool option_present (achar) char achar;
  1226. X{        
  1227. X  return((Cmd -> dash_options)[option_to_index(achar)]);
  1228. X}
  1229. X
  1230. X
  1231. XBool any_option_present ()
  1232. X{
  1233. X  int j;
  1234. X  for (j = 0; j < MAX_OPTIONS; j++) {
  1235. X      if ((Cmd -> dash_options)[j]) return(T);
  1236. X  }      
  1237. X  return(F);
  1238. X}  
  1239. X
  1240. X  
  1241. Xchar * get_option_arg (i,n) int i; int n;
  1242. X
  1243. X  /* get the nth option associated with the option whose index is 'i' */
  1244. X        
  1245. X{
  1246. X  int count;
  1247. X  Ptr_Cmd_Arg args;        
  1248. X  args = Cmd -> non_dash_arg_list;  
  1249. X  count = 0;
  1250. X  while (args != NIL) {
  1251. X        if (i == args -> option_index && ++count == n) {
  1252. X                return(args -> option);
  1253. X        }
  1254. X        args = args -> next;
  1255. X  }
  1256. X  return(NIL);
  1257. X}  
  1258. X
  1259. X
  1260. Xchar * option_arg (achar,n) char achar; int n;
  1261. X{
  1262. X  return(get_option_arg(option_to_index(achar),n));
  1263. X}
  1264. X
  1265. X
  1266. Xchar * non_option_arg (n) int n;
  1267. X{
  1268. X  return(get_option_arg(NO_OPTION,n));
  1269. X}  
  1270. X
  1271. X
  1272. Xchar * non_dash_arg (n) int n;
  1273. X
  1274. X{
  1275. X  int count = 0;
  1276. X  Ptr_Cmd_Arg arg;
  1277. X  arg = Cmd -> non_dash_arg_list;
  1278. X  while (arg != NIL) {
  1279. X        if (++count == n) return(arg -> option);
  1280. X        arg = arg -> next;
  1281. X  }
  1282. X  return(NIL);
  1283. X}
  1284. X
  1285. Xprint_args ()
  1286. X
  1287. X  /* debugging routine which prints out the Cmd structure in readable form */
  1288. X
  1289. X{
  1290. X  int j,i,n;
  1291. X  char *option,ochar;
  1292. X
  1293. X  if (Cmd == NIL) {
  1294. X        printf("\n\nNo arguments\n\n");
  1295. X        return;
  1296. X  }        
  1297. X  
  1298. X  printf("\n\narguments not associated with options: ");
  1299. X  n = 1;
  1300. X  while (T) {
  1301. X        if (NIL == (option = non_option_arg(n++))) break;
  1302. X        printf("%s ",option);
  1303. X  }
  1304. X  printf("\n");
  1305. X
  1306. X  printf("\n\noptions and their arguments:\n\n");
  1307. X  for (j = 0; j < MAX_OPTIONS; j++) {
  1308. X      ochar = index_to_option(j);
  1309. X      if (option_present(ochar)) {
  1310. X         printf("%c : \t",ochar);
  1311. X         i = 1;
  1312. X         while (T) {
  1313. X           if (NIL == (option = option_arg(ochar,i++))) break;
  1314. X           printf("%s ",option);
  1315. X         }
  1316. X         printf("     \t(# is %d)",n_option_args(ochar));
  1317. X         printf("\n");
  1318. X      }
  1319. X  }
  1320. X
  1321. X  printf("\nnumber of non-dashed args is: %d\n",n_non_dash_args());
  1322. X  printf("number of non-option args is  : %d\n",n_non_option_args());
  1323. X  
  1324. X}
  1325. X
  1326. X
  1327. X#define ALL -1
  1328. X#define NON_OPTION -2
  1329. X
  1330. Xint arg_counter (type) int type;
  1331. X
  1332. X  /* general routine which counts arguments */
  1333. X  /* if type isn't ALL or NON_OPTION then type is an index of an option */
  1334. X
  1335. X{
  1336. X  int index,count;
  1337. X  Ptr_Cmd_Arg arg;
  1338. X  arg = Cmd -> non_dash_arg_list;        
  1339. X  count = 0;
  1340. X  index = (type == NON_OPTION) ? NO_OPTION : type;
  1341. X  while (arg != NIL) {
  1342. X        if (type == ALL) {
  1343. X                count++;
  1344. X        }
  1345. X        else if (arg -> option_index == index) count++;
  1346. X        arg = arg -> next;
  1347. X  }
  1348. X  return(count);
  1349. X}
  1350. X
  1351. Xint n_option_args (achar) char achar;
  1352. X{        
  1353. X  return(arg_counter(option_to_index(achar)));
  1354. X}
  1355. X
  1356. Xint n_non_option_args ()
  1357. X{
  1358. X  return(arg_counter(NON_OPTION));
  1359. X}
  1360. X
  1361. Xint n_non_dash_args ()
  1362. X{
  1363. X  return(arg_counter(ALL));
  1364. X}
  1365. X
  1366. X
  1367. Xset_option (achar) char achar;
  1368. X{
  1369. X  (Cmd -> dash_options)[option_to_index(achar)] = T;
  1370. X}
  1371. X
  1372. X
  1373. Xerror_message (progname, argv, i, usage)
  1374. X        char *progname; char ** argv; int i; char *usage;
  1375. X{
  1376. X  fprintf(stderr,"\nillegal argument to %s : %s\n",progname,argv[i]);
  1377. X  if (usage) fprintf(stderr,"%s\n",usage);
  1378. X}
  1379. X
  1380. X
  1381. XBool
  1382. Xcheck_option_args (achar,themin,themax) char achar; int themin,themax;
  1383. X{
  1384. X  int n;
  1385. X  if (themin > themax) return(T);
  1386. X  n = n_option_args(achar);
  1387. X  return ((Bool) (n >= themin && n <= themax));
  1388. X}
  1389. X
  1390. X
  1391. Xchar legal_options (legalstring) char *legalstring;
  1392. X
  1393. X  /* are all the options the user specified characters in legalstring? */
  1394. X  /* returns ALL_LEGAL if so, otherwise the first option not in the string */
  1395. X
  1396. X{
  1397. X  int j;
  1398. X  char option, *s;
  1399. X  for (j = 0; j < MAX_OPTIONS; j++) {
  1400. X      if ((Cmd -> dash_options)[j]) {
  1401. X         option = index_to_option(j);
  1402. X         s = legalstring;
  1403. X         while (T) {
  1404. X               if (*s == '\0') return(option);
  1405. X               if (*s == option) break;
  1406. X               s++;
  1407. X         }
  1408. X      }
  1409. X  }
  1410. X  return(ALL_LEGAL);
  1411. X}
  1412. END_OF_FILE
  1413. if test 9032 -ne `wc -c <'./toolsdir/args.c'`; then
  1414.     echo shar: \"'./toolsdir/args.c'\" unpacked with wrong size!
  1415. fi
  1416. # end of './toolsdir/args.c'
  1417. fi
  1418. if test -f './toolsdir/menu.c' -a "${1}" != "-c" ; then 
  1419.   echo shar: Will not clobber existing file \"'./toolsdir/menu.c'\"
  1420. else
  1421. echo shar: Extracting \"'./toolsdir/menu.c'\" \(8281 characters\)
  1422. sed "s/^X//" >'./toolsdir/menu.c' <<'END_OF_FILE'
  1423. X#include <stdio.h>
  1424. X#ifdef UNIX
  1425. X#include <varargs.h>
  1426. X#endif
  1427. X#ifdef VMS
  1428. X#include <varargs.h>
  1429. X#endif
  1430. X#ifdef MSDOS
  1431. X#include <stdarg.h>
  1432. X#endif
  1433. X#include "basics.h"
  1434. X#include "ctools.h"
  1435. X#include "menu.h"
  1436. X#include "sys5.h"
  1437. X
  1438. X
  1439. Xstatic char line[MAX_MENU_RESPONSE_LENGTH];
  1440. X
  1441. X
  1442. Xmenu_match (
  1443. X
  1444. X     ptr_rval,ptr_ur,prompt,casetest,isub,r_no_match,r_ambiguous,
  1445. X#ifndef MSDOS
  1446. X    n_options,va_alist
  1447. X#else
  1448. X     n_options
  1449. X#endif    
  1450. X
  1451. X   )
  1452. X
  1453. X  int *ptr_rval;
  1454. X  char **ptr_ur;
  1455. X  char *prompt;
  1456. X  int casetest;
  1457. X  int isub;
  1458. X  int r_no_match;
  1459. X  int r_ambiguous;
  1460. X  int n_options;
  1461. X#ifdef VMS
  1462. X  va_dcl
  1463. X#endif
  1464. X#ifdef UNIX
  1465. X  int va_alist;
  1466. X#endif     
  1467. X{
  1468. X
  1469. X  char sline[MAX_MENU_RESPONSE_LENGTH];
  1470. X  char *options[MAX_MENU_OPTIONS];
  1471. X  int rvals[MAX_MENU_OPTIONS];
  1472. X  int j,found,len,optionlen,rval,compare,blankindex;
  1473. X#ifdef VMS
  1474. X  int args_offset = 0;    /* args_offset must be 0 in order for this to work */
  1475. X#endif
  1476. X  va_list pvar;
  1477. X        
  1478. X  if (n_options > MAX_MENU_OPTIONS) return(MENU_ERROR);
  1479. X  for (j = 0; j < MAX_MENU_RESPONSE_LENGTH; j++) line[j] = ' ';
  1480. X  
  1481. X  /* grab all the menu options and return values.  */
  1482. X  
  1483. X  blankindex = -1;
  1484. X#ifdef VMS
  1485. X  va_start_1(pvar,args_offset);
  1486. X#endif
  1487. X#ifdef UNIX
  1488. X  va_start(pvar);
  1489. X#endif
  1490. X#ifdef MSDOS
  1491. X  va_start(pvar,n_options);
  1492. X#endif
  1493. X
  1494. X  for (j = 0; j < n_options; j++) {
  1495. X      options[j] = va_arg(pvar,char *);
  1496. X      if (0 == strlen(options[j])) {
  1497. X         if (blankindex == -1) blankindex = j;
  1498. X      }
  1499. X      rvals[j] = va_arg(pvar,int);
  1500. X  }
  1501. X  va_end(pvar);
  1502. X  
  1503. X  try_again :
  1504. X  
  1505. X  /* get the user's response */
  1506. X  
  1507. X  printf("%s",prompt);
  1508. X  switch (rval = getline(stdin,line,MAX_MENU_RESPONSE_LENGTH)) {
  1509. X    case AT_EOF :
  1510. X      return(MENU_EOF);
  1511. X      /* break; */
  1512. X    case TOO_MANY_CHARS :
  1513. X     fprintf(stderr,"Response is too long to handle.  Please try again\n");
  1514. X     goto try_again;
  1515. X     /* break; */
  1516. X   default :
  1517. X     *ptr_ur = line;
  1518. X     remove_excess_blanks(sline,line);
  1519. X     len = strlen(sline);
  1520. X     break;
  1521. X }
  1522. X    
  1523. X  found = 0;
  1524. X  rval = MENU_NO_MATCH;
  1525. X  
  1526. X  if (all_whitespace(sline)) {
  1527. X     if (blankindex == -1) goto try_again;
  1528. X     rval = MENU_MATCH;
  1529. X     *ptr_rval = rvals[blankindex];
  1530. X     goto rtn;
  1531. X  }     
  1532. X  
  1533. X  for (j = 0; j < n_options; j ++) {
  1534. X
  1535. X      /* if what he typed in is longer than any option it can't match */
  1536. X        
  1537. X      optionlen = strlen(options[j]);
  1538. X      if (len > optionlen) continue;
  1539. X      
  1540. X      /* if we aren't matching initial substrings, the response must */
  1541. X      /* match exactly. */
  1542. X      
  1543. X      if (!isub && len != optionlen) continue;
  1544. X      
  1545. X      /* use different comparision functions depending on whether case */
  1546. X      /* is important or not. */
  1547. X      
  1548. X      compare = casetest ? 
  1549. X                strncmp(sline,options[j],len) :
  1550. X                nocase_compare(sline,len,options[j],len);
  1551. X                
  1552. X      /* if we must match exactly, if we find a match exit immediately. */
  1553. X      /* if we can match on an initial substring, if we've already found */
  1554. X      /* a match then we have an ambiguity, otherwise note that we've */
  1555. X      /* matched and continue looking in case of ambiguities */
  1556. X                
  1557. X      if (0 == compare) {
  1558. X         if (!isub) {
  1559. X            found = 1;
  1560. X            *ptr_rval = rvals[j];
  1561. X            rval = MENU_MATCH;
  1562. X            break;
  1563. X         }
  1564. X         if (found && isub) {
  1565. X            rval = MENU_AMBIGUOUS;
  1566. X            break;
  1567. X         }
  1568. X         else {
  1569. X            found = 1;
  1570. X            *ptr_rval = rvals[j];
  1571. X            rval = MENU_MATCH;
  1572. X         }
  1573. X      }
  1574. X      else {
  1575. X         continue;
  1576. X      }
  1577. X  }
  1578. X
  1579. X  rtn :
  1580. X  
  1581. X  switch (rval) {
  1582. X    case MENU_MATCH :
  1583. X      break;
  1584. X    case MENU_NO_MATCH :
  1585. X      if (r_no_match) {
  1586. X         printf("Your response does not match any option.  Try again\n");
  1587. X         goto try_again;
  1588. X      }
  1589. X      break;
  1590. X    case MENU_AMBIGUOUS :
  1591. X      if (r_ambiguous) {
  1592. X         printf("Your response is ambiguous.  Try again\n");
  1593. X         goto try_again;
  1594. X      }
  1595. X      break;
  1596. X    default :
  1597. X      fprintf(stderr,"Impossible case value in menu_match\n");
  1598. X      exit(-1);
  1599. X  }
  1600. X      
  1601. X  return(rval);
  1602. X  
  1603. X}
  1604. X
  1605. X
  1606. Xmenu_yes_no (prompt,allow_help) char *prompt; int allow_help;
  1607. X
  1608. X{
  1609. X  int menuval,rval;
  1610. X  char *response;
  1611. X  
  1612. X  redo :
  1613. X  
  1614. X  if (!allow_help) {
  1615. X     rval = menu_match (
  1616. X          &menuval,&response,
  1617. X          prompt,
  1618. X          0,1,0,0,2,
  1619. X          "Yes",MENU_YES,
  1620. X          "No",MENU_NO
  1621. X       );
  1622. X  }
  1623. X  else {
  1624. X     rval = menu_match (
  1625. X          &menuval,&response,
  1626. X          prompt,
  1627. X          0,1,0,0,4,
  1628. X          "Yes",MENU_YES,
  1629. X          "No",MENU_NO,
  1630. X          "?",MENU_HELP,
  1631. X          "Help",MENU_HELP
  1632. X       );
  1633. X  }
  1634. X  switch (rval) {
  1635. X    case MENU_MATCH :
  1636. X      return(menuval);
  1637. X      /* break; */
  1638. X    case MENU_NO_MATCH :
  1639. X      fprintf(stderr,"Please type 'Yes' or 'No'...\n");
  1640. X      goto redo;
  1641. X      /* break; */
  1642. X    case MENU_EOF :
  1643. X      return(MENU_EOF);
  1644. X      /* break; */
  1645. X    default :
  1646. X      fprintf(stderr,"Fatal error:  Impossible return in menu_yes_no\n");
  1647. X      exit(-1);
  1648. X  }
  1649. X
  1650. X  return(0);
  1651. X}
  1652. X
  1653. X
  1654. Xint menu_data_help_or_abort (prompt,abortstring,ptr_response)
  1655. X
  1656. X  char *prompt, *abortstring, **ptr_response;
  1657. X
  1658. X{
  1659. X  int rval,menuval;
  1660. X  rval = menu_match (
  1661. X       &menuval,ptr_response,
  1662. X       prompt,
  1663. X       0,1,0,1,3,
  1664. X       abortstring,MENU_ABORT,
  1665. X       "?",MENU_HELP,
  1666. X       "Help",MENU_HELP
  1667. X    );
  1668. X  switch (rval) {
  1669. X    case MENU_NO_MATCH :
  1670. X      return(MENU_DATA);
  1671. X      /* break; */
  1672. X    case MENU_MATCH :
  1673. X      return(menuval);
  1674. X      /* break; */
  1675. X    case MENU_EOF :
  1676. X      return(MENU_EOF);
  1677. X      /* break; */
  1678. X    default :
  1679. X      fprintf(stderr,"Impossible return from menu_data_help_or_abort\n");
  1680. X      exit(-1);
  1681. X  }
  1682. X
  1683. X  return(0);
  1684. X}
  1685. X
  1686. X
  1687. Xmenu_number_help_or_abort (prompt,abortstring,low,high,ptr_ival)
  1688. X
  1689. X  char *prompt, *abortstring;
  1690. X  int low,high,*ptr_ival;
  1691. X
  1692. X{
  1693. X  char *response,errprompt[80],numstring[MAX_MENU_RESPONSE_LENGTH];
  1694. X#ifdef MSDOS
  1695. X  int rval;
  1696. X#else
  1697. X  int rval,check;
  1698. X#endif
  1699. X
  1700. X#ifdef MSDOS
  1701. X  if (!(low <= high))
  1702. X#else
  1703. X  if (!(check = (low <= high)))
  1704. X#endif
  1705. X     nbuffconcat(errprompt,1,"Please enter a non-negative number...\n\n");
  1706. X  else
  1707. X     sprintf(errprompt,"Please enter a number between %d and %d\n\n",low,high);
  1708. X  
  1709. X  reask :     
  1710. X     
  1711. X  rval = menu_data_help_or_abort(prompt,abortstring,&response);
  1712. X  switch (rval) {
  1713. X    case MENU_EOF :
  1714. X    case MENU_ABORT :
  1715. X    case MENU_HELP :
  1716. X      return(rval);
  1717. X      /* break; */
  1718. X    case MENU_DATA :
  1719. X      remove_excess_blanks(numstring,response);
  1720. X      switch (*ptr_ival = str_to_pos_int(numstring,0,MAXINT)) {
  1721. X        case -1:
  1722. X        case -2:
  1723. X          fprintf(stderr,"%s",errprompt);
  1724. X          goto reask;
  1725. X          /* break; */
  1726. X        default:
  1727. X          return(MENU_DATA);
  1728. X          /* break; */
  1729. X      }
  1730. X  }
  1731. X
  1732. X  return(0);
  1733. X}
  1734. X
  1735. X
  1736. Xmenu_yes_no_abort_or_help (prompt,abortstring,helpallowed,return_for_yes)
  1737. X
  1738. X/*
  1739. X    Returns one of MENU_YES, MENU_NO, MENU_ABORT or MENU_HELP.
  1740. X    If !helpallowed, MENU_HELP will not be returned.  
  1741. X    If return_for_yes is 0, hitting return will re-prompt.
  1742. X    If it is 1, hitting return is like typing yes.
  1743. X    If it is any other value, hitting return is like typing no.
  1744. X*/
  1745. X
  1746. X  char *prompt;
  1747. X  char *abortstring;
  1748. X  int helpallowed; 
  1749. X  int return_for_yes;
  1750. X
  1751. X{
  1752. X  int menuval,rval;
  1753. X  char *response;
  1754. X  
  1755. X  redo :
  1756. X  
  1757. X  if (!helpallowed) {
  1758. X     rval = menu_match (
  1759. X          &menuval,&response,
  1760. X          prompt,
  1761. X          0,1,0,0,4,
  1762. X          "Yes",MENU_YES,
  1763. X          "No",MENU_NO,
  1764. X          abortstring,MENU_ABORT,
  1765. X          "",MENU_RETURN
  1766. X       );
  1767. X  }
  1768. X  else {
  1769. X     rval = menu_match (
  1770. X          &menuval,&response,
  1771. X          prompt,
  1772. X          0,1,0,0,6,
  1773. X          "Yes",MENU_YES,
  1774. X          "No",MENU_NO,
  1775. X          "?",MENU_HELP,
  1776. X          "Help",MENU_HELP,
  1777. X          abortstring,MENU_ABORT,
  1778. X          "",MENU_RETURN
  1779. X       );
  1780. X  }
  1781. X  switch (rval) {
  1782. X    case MENU_MATCH :
  1783. X      if (menuval != MENU_RETURN) return(menuval);
  1784. X      switch (return_for_yes) {
  1785. X        case NO_DEFAULT :
  1786. X          goto redo;
  1787. X          /* break; */
  1788. X        case DEFAULT_YES :
  1789. X          return(MENU_YES);
  1790. X          /* break; */
  1791. X        default :
  1792. X          return(MENU_NO);
  1793. X          /* break; */
  1794. X      }
  1795. X      /* break; */
  1796. X    case MENU_NO_MATCH :
  1797. X      printf("Please type 'Yes' or 'No'...\n");
  1798. X      goto redo;
  1799. X      /* break; */
  1800. X    case MENU_EOF :
  1801. X      return(MENU_EOF);
  1802. X      /* break; */
  1803. X    default :
  1804. X      fprintf(stderr,"Fatal error:  Impossible return in menu_yes_no\n");
  1805. X      exit(-1);
  1806. X  }
  1807. X
  1808. X  return(0);
  1809. X}
  1810. END_OF_FILE
  1811. if test 8281 -ne `wc -c <'./toolsdir/menu.c'`; then
  1812.     echo shar: \"'./toolsdir/menu.c'\" unpacked with wrong size!
  1813. fi
  1814. # end of './toolsdir/menu.c'
  1815. fi
  1816. if test -f './toolsdir/menu.h' -a "${1}" != "-c" ; then 
  1817.   echo shar: Will not clobber existing file \"'./toolsdir/menu.h'\"
  1818. else
  1819. echo shar: Extracting \"'./toolsdir/menu.h'\" \(4423 characters\)
  1820. sed "s/^X//" >'./toolsdir/menu.h' <<'END_OF_FILE'
  1821. X/* You must include "<ctools.h>" before including this file. */
  1822. X
  1823. X#define MENU_EOF -1
  1824. X#define MENU_MATCH 0
  1825. X#define MENU_AMBIGUOUS 1
  1826. X#define MENU_NO_MATCH 2        
  1827. X#define MENU_ERROR 3
  1828. X#define MENU_RETURN 4
  1829. X
  1830. X#define MAX_MENU_OPTIONS 20
  1831. X#define MAX_MENU_RESPONSE_LENGTH 255
  1832. X
  1833. X
  1834. Xextern int menu_match();
  1835. X
  1836. X/* menu_match (
  1837. X
  1838. X        int *ptr_rval,
  1839. X        char **ptr_user_response,
  1840. X        char *prompt,
  1841. X        int case_significant,
  1842. X        int initial_substring_sufficient,
  1843. X        int repeat_if_no_match,
  1844. X        int repeat_if_ambiguous,
  1845. X        int n_options,
  1846. X        char *option1, int rval1,
  1847. X        char *option2, int rval2,
  1848. X        .
  1849. X        .
  1850. X        .
  1851. X
  1852. X    );
  1853. X
  1854. X    Returns one of MENU_MATCH, MENU_AMBIGUOUS, MENU_NO_MATCH, and MENU_ERROR.
  1855. X    If MENU_MATCH is returned, *ptr_rval contains the value that the caller
  1856. X    asked to be returned.  *ptr_user_response is what exactly what the user
  1857. X    typed in, minus the linefeed at the end.
  1858. X    
  1859. X    prompt is a character string that is printed out.  A line of input is
  1860. X    then read from the terminal, stripped of excess blanks, and compared
  1861. X    with the menu items.  Up to MAX_MENU_OPTIONS can be specified.  Each
  1862. X    option is a character string and has an associated integer return value.
  1863. X    
  1864. X    If case_significant is not zero, the user's response will be checked
  1865. X    against the options with upper/lower case distinction. 
  1866. X    If initial_substring_sufficient is not zero, then a match will occur
  1867. X    if the user's response is the same as an initial substring of an option,
  1868. X    otherwise the response must match the option exactly.
  1869. X    
  1870. X    If more than one menu option matches the response, MENU_AMBIGUOUS is
  1871. X    returned.  If n_options exceeds MAX_MENU_OPTIONS or the read fails
  1872. X    MENU_ERROR is returned.  If no option matches the response, MENU_NO_MATCH
  1873. X    is returned.  However, if repeat_if_no_match and/or repeat_if_ambiguous
  1874. X    are non_zero, the user is prompted again until he answers correctly if
  1875. X    he answers wrongly/ambiguously, respectively.
  1876. X    
  1877. X    If "" is not specified as an option, and the user enters a blank line,
  1878. X    the routine simply prompts the user again.  It is impossible to match
  1879. X    on a string of blanks (e.g., "  "), because any blank line the user
  1880. X    types is considered to be "".
  1881. X    
  1882. X    If the response the user types is too long, an error message is printed
  1883. X    out and the user is asked to try again.
  1884. X    
  1885. X*/
  1886. X
  1887. X
  1888. X#define MENU_NO 0
  1889. X#define MENU_YES 1
  1890. X#define MENU_HELP 2
  1891. X#define MENU_ABORT 3
  1892. X#define MENU_DATA 4
  1893. X
  1894. Xextern int menu_yes_no();
  1895. X
  1896. X/* menu_yes_no (prompt,allow_help) char *prompt; int allow_help;
  1897. X
  1898. X        returns one of MENU_NO, MENU_YES or, if help is allowed,
  1899. X        MENU_HELP.  Help can be obtained via "?" or any initial
  1900. X        substring of "Help", case independently.  Returns MENU_EOF
  1901. X        if end of file encountered when reading. 
  1902. X
  1903. X        Yes or no can be obtained via any case independent initial
  1904. X        substring of "Yes" or "No" respectively.
  1905. X
  1906. X*/
  1907. X
  1908. X
  1909. X#define DEFAULT_YES 0
  1910. X#define DEFAULT_NO 1
  1911. X#define NO_DEFAULT 2
  1912. X
  1913. Xextern int menu_yes_no_abort_or_help ();
  1914. X
  1915. X/*  menu_yes_no_abort_or_help (prompt,abortstring,helpallowed,return_for_yes)
  1916. X
  1917. X    char *prompt, *abortstring;
  1918. X    int helpallowed; 
  1919. X    int return_for_yes;
  1920. X
  1921. X    Returns one of MENU_YES, MENU_NO, MENU_ABORT, MENU_HELP or MENU_EOF.
  1922. X    If !helpallowed, MENU_HELP will not be returned.  
  1923. X    If return_for_yes is DEFAULT_NO, hitting return will re-prompt.
  1924. X    If it is DEFAULT_YES, hitting return is like typing yes.
  1925. X    If it is any other value, hitting return is like typing no.
  1926. X
  1927. X*/    
  1928. X
  1929. Xextern int menu_data_help_or_abort ();
  1930. X
  1931. X/*
  1932. X
  1933. Xextern int menu_data_help_or_abort (prompt,abortstring,ptr_response)
  1934. X
  1935. X  char *prompt, *abortstring, **ptr_response;
  1936. X
  1937. X  Returns either MENU_ABORT, MENU_HELP or MENU_DATA.  If MENU_DATA is
  1938. X  returned, *response contains the user's response.  MENU_HELP is
  1939. X  returned in the user types in "?" or any initial substring of "Help"
  1940. X  (case independently).
  1941. X  
  1942. X*/  
  1943. X  
  1944. X
  1945. Xextern int menu_number_help_or_abort ();
  1946. X
  1947. X/*
  1948. Xmenu_number_help_or_abort (prompt,abortstring,low,high,ptr_ival)
  1949. X
  1950. X  char *prompt; *abortstring;
  1951. X  int low,high,*ptr_ival;
  1952. X
  1953. X  Returns either MENU_DATA, MENU_ABORT, MENU_HELP or MENU_EOF.
  1954. X  If low > high any number will be considered valid, otherwise the
  1955. X  range is checked, inclusivewise.  If MENU_DATA is returned, *ptr_ival
  1956. X  contains the number entered.
  1957. X
  1958. X  At the moment number can only be non-negative.
  1959. X*/
  1960. END_OF_FILE
  1961. if test 4423 -ne `wc -c <'./toolsdir/menu.h'`; then
  1962.     echo shar: \"'./toolsdir/menu.h'\" unpacked with wrong size!
  1963. fi
  1964. # end of './toolsdir/menu.h'
  1965. fi
  1966. if test -f './update.c' -a "${1}" != "-c" ; then 
  1967.   echo shar: Will not clobber existing file \"'./update.c'\"
  1968. else
  1969. echo shar: Extracting \"'./update.c'\" \(6171 characters\)
  1970. sed "s/^X//" >'./update.c' <<'END_OF_FILE'
  1971. X/* update.c */
  1972. X#include <stdio.h>
  1973. X#include <ctype.h>
  1974. X
  1975. X#ifdef TMC
  1976. X#include <ctools.h>
  1977. X#else
  1978. X#include "ctools.h"
  1979. X#endif
  1980. X#include "args.h"
  1981. X#include "menu.h"
  1982. X#include "mem.h"
  1983. X
  1984. X#include "rolofilz.h"
  1985. X#include "rolodefs.h"
  1986. X#include "datadef.h"
  1987. X#include "choices.h"
  1988. X
  1989. X#define index strchr
  1990. X
  1991. X
  1992. Xchar *get_new_value () 
  1993. X{
  1994. X  char buffer[200];
  1995. X  int rval;
  1996. X  switch (rval = getline(stdin,buffer,199)) {
  1997. X    case AT_EOF :
  1998. X      user_eof();
  1999. X      break;
  2000. X    case TOO_MANY_CHARS :
  2001. X      fprintf(stderr,"Line too long, truncated...\n");
  2002. X      sleep(1);
  2003. X      break;
  2004. X    default :
  2005. X      if ('\\' == *buffer && rval == 1) return(0);
  2006. X      break;
  2007. X  }
  2008. X  return(copystr(buffer));
  2009. X}  
  2010. X  
  2011. X
  2012. XPtr_Rolo_Entry copy_entry (lentry) Ptr_Rolo_Entry lentry;
  2013. X{
  2014. X  Ptr_Rolo_Entry new_entry;        
  2015. X  int j,n;        
  2016. X  char **otherfields;
  2017. X  
  2018. X  new_entry = (Ptr_Rolo_Entry) rolo_emalloc(sizeof(Rolo_Entry));
  2019. X  
  2020. X  /* copy the basic fields, but get a new timestamp */
  2021. X  
  2022. X  for (j = 0; j < N_BASIC_FIELDS - 1; j++) {
  2023. X      set_basic_rolo_field(j,new_entry,copystr(get_basic_rolo_field(j,lentry)));
  2024. X  }
  2025. X  set_basic_rolo_field(N_BASIC_FIELDS - 1,new_entry,timestring());
  2026. X  
  2027. X  /* copy the user-defined fields, if necessary */
  2028. X  
  2029. X  set_n_others(new_entry,n = get_n_others(lentry));
  2030. X  if (n > 0) {
  2031. X     otherfields = (char **) rolo_emalloc(n * sizeof(char *));
  2032. X     new_entry -> other_fields = otherfields;
  2033. X     for (j = 0; j < n; j++) {  
  2034. X         set_other_field(j,new_entry,copystr(get_other_field(j,lentry)));
  2035. X     }
  2036. X  }     
  2037. X  else new_entry -> other_fields = 0;     
  2038. X     
  2039. X  return(new_entry);     
  2040. X     
  2041. X}
  2042. X
  2043. X
  2044. Xrolo_update_mode (rlink) Ptr_Rolo_List rlink;
  2045. X
  2046. X/* Update the fields of an entry.  The user is not allowed to modify the */
  2047. X/* timestamp field. */
  2048. X
  2049. X{
  2050. X  int rval,menuval,findex,updated,newlen,n,nfields,j,name_changed;
  2051. X  char *response,*s,*newfield,*newval,*other, **others;
  2052. X  Ptr_Rolo_Entry lentry,old_entry;
  2053. X
  2054. X  if(read_only)
  2055. X  {
  2056. X    printf("Readonly mode: Updates not allowed.\n");
  2057. X    sleep(2);
  2058. X    return(1);
  2059. X  }
  2060. X
  2061. X  cancel_update :
  2062. X  
  2063. X  lentry = copy_entry(old_entry = get_entry(rlink));
  2064. X
  2065. X  updated = 0;
  2066. X  name_changed = 0;   
  2067. X  
  2068. X  redisplay :
  2069. X  
  2070. X  display_entry_for_update(updated ? lentry : old_entry);
  2071. X  nfields = (N_BASIC_FIELDS - 1) + get_n_others(lentry);
  2072. X  
  2073. X  reask :  
  2074. X  
  2075. X  cathelpfile(UPDATEMENU,(char *)NULL,0);  
  2076. X  
  2077. X  rval = menu_match (
  2078. X       &menuval,&response,
  2079. X       ": ",
  2080. X       0,1,0,1,4,
  2081. X       "\\",U_ABORT,
  2082. X       "?",U_HELP,
  2083. X       "Help",U_HELP,
  2084. X       "",U_END_UPDATE
  2085. X    );
  2086. X    
  2087. X  switch (rval) {    
  2088. X    
  2089. X    case MENU_MATCH :
  2090. X  
  2091. X      switch (menuval) {
  2092. X
  2093. X        case U_HELP :
  2094. X          cathelpfile(UPDATEHELP,"updating",1);
  2095. X          any_char_to_continue();
  2096. X          clear_the_screen();
  2097. X          goto redisplay;
  2098. X
  2099. X        case U_ABORT :
  2100. X          if (updated) {
  2101. X             printf("Previous updates to fields in this entry ignored\n");
  2102. X          }
  2103. X          return(0);
  2104. X          /* break; */
  2105. X
  2106. X        case U_END_UPDATE :
  2107. X          if (!updated) goto reask;
  2108. X          display_entry(lentry);
  2109. X          if (MENU_YES == rolo_menu_yes_no (
  2110. X                   "Confirm Update? ",DEFAULT_YES,1,
  2111. X                   CONFIRMHELP,"confirming update"
  2112. X                )) {
  2113. X             printf("Update confirmed\n");
  2114. X             sleep(1);
  2115. X             set_entry(rlink,lentry);
  2116. X             if (name_changed) {
  2117. X                rolo_delete(rlink);
  2118. X                rolo_insert(rlink,compare_links);
  2119. X             }
  2120. X             changed = 1;
  2121. X             return(0);
  2122. X          }
  2123. X          else {   
  2124. X             printf("Updates ignored...\n");
  2125. X             sleep(1);
  2126. X             updated = 0;
  2127. X             goto cancel_update;
  2128. X          }
  2129. X         /* break; */
  2130. X       
  2131. X      }
  2132. X      break;
  2133. X     
  2134. X    case MENU_NO_MATCH : 
  2135. X
  2136. X      /* check that the response is an integer within range */
  2137. X
  2138. X      findex = str_to_pos_int(response,1,nfields+1);
  2139. X      if (findex < 0) {
  2140. X         printf("Not a valid number...Please try again\n");
  2141. X         goto reask;
  2142. X      }
  2143. X      findex--;
  2144. X
  2145. X      /* we can either be updating a standard field or a user-defined field */
  2146. X      /* or adding a new field */
  2147. X
  2148. X      if (findex < N_BASIC_FIELDS - 1) {
  2149. X         name_changed = (findex == 0);
  2150. X         printf("Updating '%s'\n",Field_Names[findex]);
  2151. X         printf("Old value: %s\n",get_basic_rolo_field(findex,lentry));
  2152. X         printf("New value: ");
  2153. X         if (0 == (newval = copystr(get_new_value()))) break;
  2154. X         set_basic_rolo_field(findex,lentry,newval);
  2155. X         updated = 1;
  2156. X      }
  2157. X      else if (findex != nfields) {
  2158. X         findex -= N_BASIC_FIELDS - 1;
  2159. X         printf("Updating \'");
  2160. X         s = other = get_other_field(findex,lentry);
  2161. X         while (*s != ':') putc(*s++,stdout);
  2162. X         printf("\' field\n");
  2163. X         printf("Old value: %s\n",++s);
  2164. X         printf("New value: ");
  2165. X         if (0 == (newval = copystr(get_new_value()))) break;
  2166. X         if (strlen(newval) == 0) {
  2167. X            for (j = findex; j < get_n_others(lentry); j++) {
  2168. X                set_other_field(j,lentry,get_other_field(j+1,lentry));
  2169. X            }
  2170. X            set_n_others(lentry,get_n_others(lentry) - 1);
  2171. X         }
  2172. X         else {   
  2173. X            *s = '\0';
  2174. X            newlen = strlen(other) + strlen(newval) + 2;
  2175. X            newfield = rolo_emalloc(newlen);
  2176. X            nbuffconcat(newfield,3,other," ",newval);
  2177. X            set_other_field(findex,lentry,newfield);
  2178. X         }
  2179. X         updated = 1;
  2180. X      }
  2181. X      else {
  2182. X        loop:
  2183. X        printf("New field (<name>: <value>): ");
  2184. X        if (0 == (newfield = copystr(get_new_value()))) break;
  2185. X        if (0 == (char *)index(newfield,':')) {
  2186. X           fprintf(stderr,"No field name.  Use a ':'...\n");
  2187. X           goto loop;
  2188. X        }
  2189. X        n = get_n_others(lentry);
  2190. X        set_n_others(lentry,n + 1);
  2191. X        others = (char **) rolo_emalloc((n + 1) * sizeof(char *));
  2192. X        for (j = 0; j < n; j++) others[j] = get_other_field(j,lentry);
  2193. X        others[n] = newfield;
  2194. X        lentry -> other_fields = others;
  2195. X        updated = 1;
  2196. X      }
  2197. X      break;
  2198. X
  2199. X    case MENU_EOF :
  2200. X      user_eof();
  2201. X      break;
  2202. X      
  2203. X    default :      
  2204. X      fprintf(stderr,"Impossible return from update menu_match\n");
  2205. X      save_and_exit(-1);
  2206. X      break;
  2207. X     
  2208. X  }
  2209. X
  2210. X  goto redisplay;
  2211. X
  2212. X}
  2213. END_OF_FILE
  2214. if test 6171 -ne `wc -c <'./update.c'`; then
  2215.     echo shar: \"'./update.c'\" unpacked with wrong size!
  2216. fi
  2217. # end of './update.c'
  2218. fi
  2219. echo shar: End of archive 2 \(of 4\).
  2220. cp /dev/null ark2isdone
  2221. MISSING=""
  2222. for I in 1 2 3 4 ; do
  2223.     if test ! -f ark${I}isdone ; then
  2224.     MISSING="${MISSING} ${I}"
  2225.     fi
  2226. done
  2227. if test "${MISSING}" = "" ; then
  2228.     echo You have unpacked all 4 archives.
  2229.     rm -f ark[1-9]isdone
  2230. else
  2231.     echo You still need to unpack the following archives:
  2232.     echo "        " ${MISSING}
  2233. fi
  2234. ##  End of shell archive.
  2235. exit 0
  2236.